<?php
// +----------------------------------------------------------------------
// | ThinkBLOG (Build on ThinkPHP)
// +----------------------------------------------------------------------
// | @link ( http://www.yurnero.net )
// +----------------------------------------------------------------------
// | @licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | @author nicholas <nicholasinlove@126.com>
// +----------------------------------------------------------------------
// | $Id: MetasModel.class.php 117 2012-04-13 08:32:56Z nicholasinlove1986@gmail.com $
// +----------------------------------------------------------------------


class MetasModel extends CommonModel {
	
	/**
	 * 
	 * 字段信息
	 * 
	 * @var Model
	 */
	protected $fields = array (
		0 => 'metaid', 
		1 => 'name', 
		2 => 'slug', 
		3 => 'type', 
		4 => 'description', 
		5 => 'count', 
		6 => 'order', 
		7 => 'parent', 
		'_autoinc' => true, 
		'_pk' => 'metaid', 
		'_type' => array (
			'metaid' => 'int(10) unsigned', 
			'name' => 'varchar(200)', 
			'slug' => 'varchar(200)', 
			'type' => 'varchar(32)', 
			'description' => 'varchar(200)', 
			'count' => 'int(10) unsigned', 
			'order' => 'int(10) unsigned', 
			'parent' => 'int(10) unsigned' 
		) 
	);
	
	/**
	 * 自动验证定义
	 *
	 * @access public
	 * @var Model
	 */
	public $_validate	=	array(
		array ('name', 'require', '错误：必须为项目命名。' ),
		array ('slug', 'checkSlug', '错误：项目无法被转换为缩略名。', 0, 'callback' ),
		array ('order', 'require', '错误：必须填写排序。' ),
		array ('order', 'number', '错误：排序通常是一个数字。' ),
		//array('name','','错误：项目已存在。',0,'unique',1),
		//array('slug','','错误：缩略名已经存在。',0,'unique',1),
	);

	/**
	 * 自动完成定义
	 *
	 * @access public
	 * @var Model
	 */
	public $_auto		=	array(
		array ('slug', 'slugName', 3, 'callback' ),
		array ('type', 'emptyType', 3, 'callback' ),
	);
	
	/**
	 * 判断别名转换到缩略名后是否合法
	 *
	 * @access public
	 * @param $slug 别名
	 * 
	 * @return bool
	 */
	protected function checkSlug() {
		if ($_POST ['slug'] != '') {
			$slug = tslug_name ( $_POST ['slug'] );
			if (empty ( $slug )) {
				return false;
			}
		}
		return true;
	}
	
	protected function slugName() {
		return strtolower ( urlencode ( tslug_name ( empty ( $_POST ['slug'] ) ? $_POST ['name'] : $_POST ['slug'] ) ) );
	}
	
	protected function emptyType() {
		return empty ( $_POST ['type'] ) ? 'category' : $_POST ['type'];
	}
	
	/**
	 * 获取分类数据以二维数组返回
	 *
	 * @access  public
	 * @return  array
	 */
	public function getCategoryArray() {
	
		$sql = "select c.metaid, c.parent, c.slug, c.name, c.count, c.order, c.description, count(s.metaid) as has_children ".
               " from " . C ( 'DB_PREFIX' ) . "metas as c ".
               " left join " . C ( 'DB_PREFIX' ) . "metas as s on s.parent = c.metaid where c.type = 'category' ".
               " group by c.metaid ".
               ' order by c.parent, c.order asc ';	
	    $res = $this->query ( $sql );	
		
		return $res;
	}
	
	/**
	 * 获取标签数据以二维数组返回
	 *
	 * @access  public
	 * @return  array
	 */
	public function getTagArray() {
		$map = array ();
		$map ['type'] = 'tag';
		$field = 'metaid,slug,name,count,description';
		$order = 'count desc';
		return $this->getListByMap ( $map, $field, $order );
	}
	
	/**
	 * 过滤和排序所有分类，返回一个带有缩进级别的数组
	 *
	 * @access  private
	 * @param   int     $cat_id     上级分类ID
	 * @param   array   $arr        含有所有分类的数组
	 * @param   int     $level      级别
	 * @return  void
	 */
	public function getCategoryOptions($spec_cat_id = 0, $arr) {
		static $cat_options = array ();
		
		if (isset ( $cat_options [$spec_cat_id] )) {
			return $cat_options [$spec_cat_id];
		}
		
		if (! isset ( $cat_options [0] )) {
			$level = $last_cat_id = 0;
			$options = $cat_id_array = $level_array = array ();
			$data = S ( 'category' );
			if ($data === false) {
				while ( ! empty ( $arr ) ) {
					foreach ( $arr as $key => $value ) {
						$cat_id = $value ['metaid'];
						if ($level == 0 && $last_cat_id == 0) {
							if ($value ['parent'] > 0) {
								break;
							}
							
							$options [$cat_id] = $value;
							$options [$cat_id] ['level'] = $level;
							$options [$cat_id] ['id'] = $cat_id;
							$options [$cat_id] ['name'] = $value ['name'];
							unset ( $arr [$key] );
							
							if ($value ['has_children'] == 0) {
								continue;
							}
							$last_cat_id = $cat_id;
							$cat_id_array = array ($cat_id );
							$level_array [$last_cat_id] = ++ $level;
							continue;
						}
						
						if ($value ['parent'] == $last_cat_id) {
							$options [$cat_id] = $value;
							$options [$cat_id] ['level'] = $level;
							$options [$cat_id] ['id'] = $cat_id;
							$options [$cat_id] ['name'] = $value ['name'];
							unset ( $arr [$key] );
							
							if ($value ['has_children'] > 0) {
								if (end ( $cat_id_array ) != $last_cat_id) {
									$cat_id_array [] = $last_cat_id;
								}
								$last_cat_id = $cat_id;
								$cat_id_array [] = $cat_id;
								$level_array [$last_cat_id] = ++ $level;
							}
						} elseif ($value ['parent'] > $last_cat_id) {
							break;
						}
					}
					
					$count = count ( $cat_id_array );
					if ($count > 1) {
						$last_cat_id = array_pop ( $cat_id_array );
					} elseif ($count == 1) {
						if ($last_cat_id != end ( $cat_id_array )) {
							$last_cat_id = end ( $cat_id_array );
						} else {
							$level = 0;
							$last_cat_id = 0;
							$cat_id_array = array ();
							continue;
						}
					}
					
					if ($last_cat_id && isset ( $level_array [$last_cat_id] )) {
						$level = $level_array [$last_cat_id];
					} else {
						$level = 0;
					}
				}
				//如果数组过大，不采用静态缓存方式
				if (count ( $options ) <= 2000) {
					S ( 'category', $options );
				}
			} else {
				$options = $data;
			}
			$cat_options [0] = $options;
		} else {
			$options = $cat_options [0];
		}
		
		if (! $spec_cat_id) {
			return $options;
		} else {
			if (empty ( $options [$spec_cat_id] )) {
				return array ();
			}
			
			$spec_cat_id_level = $options [$spec_cat_id] ['level'];
			
			foreach ( $options as $key => $value ) {
				if ($key != $spec_cat_id) {
					unset ( $options [$key] );
				} else {
					break;
				}
			}
			
			$spec_cat_id_array = array ();
			foreach ( $options as $key => $value ) {
				if (($spec_cat_id_level == $value ['level'] && $value ['metaid'] != $spec_cat_id) || ($spec_cat_id_level > $value ['level'])) {
					break;
				} else {
					$spec_cat_id_array [$key] = $value;
				}
			}
			$cat_options [$spec_cat_id] = $spec_cat_id_array;
			
			return $spec_cat_id_array;
		}
	}
	
	/**
	 * 获得指定分类下的子分类
	 *
	 * @access  public
	 * @param   int     $cat_id     分类的ID,默认为父ID
	 * @param   int     $selected   当前选中分类的ID
	 * @param   int     $level      限定返回的级数。为0时返回所有级数
	 * @param   boolean $re_type    返回的类型: 值为真时返回下拉列表,否则返回数组
	 * @return  mix
	 */
	public function getCategoryList($cat_id = 0, $selected = 0, $level = 0, $re_type = true) {
		static $res = NULL;
		if ($res === NULL) {
			$data = S ( 'category_array' );
			if ($data === false) {
				$res = $this->getCategoryArray ();
				//如果数组过大，不采用静态缓存方式
				if (count ( $res ) <= 1000) {
					S ( 'category_array', $res );
				}
			} else {
				$res = $data;
			}
		}
		
		if (empty ( $res ) == true) {
			return $re_type ? '' : array ();
		}
		
		$options = $this->getCategoryOptions ( $cat_id, $res ); // 获得指定分类下的子分类的数组
		

		$children_level = 99999; //大于这个分类的将被删除
		/* 截取到指定的缩减级别 */
		if ($level > 0) {
			if ($cat_id == 0) {
				$end_level = $level;
			} else {
				$first_item = reset ( $options ); // 获取第一个元素
				$end_level = $first_item ['level'] + $level;
			}
			
			/* 保留level小于end_level的部分 */
			foreach ( $options as $key => $val ) {
				if ($val ['level'] >= $end_level) {
					unset ( $options [$key] );
				}
			}
		}
		
		if ($re_type == true) {
			$select = '';
			foreach ( $options as $var ) {
				$select .= '<option value="' . $var ['metaid'] . '" ';
				$select .= ($selected == $var ['metaid']) ? "selected='selected'" : '';
				$select .= '>';
				if ($var ['level'] > 0) {
					$select .= str_repeat ( '&nbsp;', $var ['level'] * 4 );
				}
				$select .= htmlspecialchars ( addslashes ( $var ['name'] ), ENT_QUOTES ) . '</option>';
			}
			
			return $select;
		} else {
			foreach ( $options as $key => $value ) {
				$options [$key] ['url'] = '';
			}
			
			return $options;
		}
	}
	
	/**
	 * 获取标签
	 *
	 * @access  public
	 * @param   boolean $re_type    返回的类型: 值为真时返回下拉列表,否则返回数组
	 * @return  array
	 */
	public function getTagList( $re_type = true ) {	
		static $res = NULL;
		if ($res === NULL) {
			$data = S ( 'tag' );
			if ($data === false) {
				$res = $this->getTagArray ();
				S ( 'tag', $res );
			} else {
				$res = $data;
			}
		}
		
		if (empty ( $res ) == true) {
			return $re_type ? '' : array ();
		}
		
		if ($re_type == true) {
			foreach ($res as $var ) {
				$select .= "<option value='{$var['metaid']}' ";
				$select .= ">";
				$select .= "{$var['name']}</option>";	
			}			
			return $select;
		} else {		
			return $res;
        }
	}
	
}